#ifndef __TPS_MTD_CLASS_IMPL_H__
#define __TPS_MTD_CLASS_IMPL_H__

#define TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Ret mtd_(
#define TPS_MTD_PROXY_CLASS_IMPL_MTD_END() )

#define TPS_MTD_PROXY_CLASS_IMPL(mtd_) \
	template <typename ThisType, typename MtdType, unsigned ParamsCount, bool IsConstMtd> \
	struct mtd_##ProxyMtdWrap; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 0, false> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) TPS_MTD_PROXY_CLASS_IMPL_MTD_END() \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 0, false); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 0, true> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) TPS_MTD_PROXY_CLASS_IMPL_MTD_END() const \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 0, true); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 1, false> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 1, false); \
			Pack->template PutParameter<Param1>(1, prm1); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 1, true> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() const \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 1, true); \
			Pack->template PutParameter<Param1>(1, prm1); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 2, false> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 2, false); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 2, true> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() const \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 2, true); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 3, false> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
		typedef typename MtdTuple::Param3 Param3; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2, Param3 prm3 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 3, false); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
			Pack->template PutParameter<Param3>(3, prm3); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
            Tps::Private::OutParamGetter<Param3>::Get(Unpacker, 3, prm3); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 3, true> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
		typedef typename MtdTuple::Param3 Param3; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2, Param3 prm3 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() const \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 3, true); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
			Pack->template PutParameter<Param3>(3, prm3); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
            Tps::Private::OutParamGetter<Param3>::Get(Unpacker, 3, prm3); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 4, false> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
		typedef typename MtdTuple::Param3 Param3; \
		typedef typename MtdTuple::Param4 Param4; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2, Param3 prm3, Param4 prm4 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 4, false); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
			Pack->template PutParameter<Param3>(3, prm3); \
			Pack->template PutParameter<Param4>(4, prm4); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
            Tps::Private::OutParamGetter<Param3>::Get(Unpacker, 3, prm3); \
            Tps::Private::OutParamGetter<Param4>::Get(Unpacker, 4, prm4); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 4, true> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
		typedef typename MtdTuple::Param3 Param3; \
		typedef typename MtdTuple::Param4 Param4; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2, Param3 prm3, Param4 prm4 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() const \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 4, true); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
			Pack->template PutParameter<Param3>(3, prm3); \
			Pack->template PutParameter<Param4>(4, prm4); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
            Tps::Private::OutParamGetter<Param3>::Get(Unpacker, 3, prm3); \
            Tps::Private::OutParamGetter<Param4>::Get(Unpacker, 4, prm4); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 5, false> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
		typedef typename MtdTuple::Param3 Param3; \
		typedef typename MtdTuple::Param4 Param4; \
		typedef typename MtdTuple::Param5 Param5; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2, Param3 prm3, Param4 prm4, Param5 prm5 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 5, false); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
			Pack->template PutParameter<Param3>(3, prm3); \
			Pack->template PutParameter<Param4>(4, prm4); \
			Pack->template PutParameter<Param5>(5, prm5); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
            Tps::Private::OutParamGetter<Param3>::Get(Unpacker, 3, prm3); \
            Tps::Private::OutParamGetter<Param4>::Get(Unpacker, 4, prm4); \
            Tps::Private::OutParamGetter<Param5>::Get(Unpacker, 5, prm5); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	}; \
	template <typename ThisType, typename MtdType> \
	struct mtd_##ProxyMtdWrap<ThisType, MtdType, 5, true> \
		: public virtual IFacePSType \
	{ \
	private: \
		typedef MtdType MtdTuple; \
		typedef typename MtdTuple::Ret Ret; \
		typedef typename MtdTuple::Param1 Param1; \
		typedef typename MtdTuple::Param2 Param2; \
		typedef typename MtdTuple::Param3 Param3; \
		typedef typename MtdTuple::Param4 Param4; \
		typedef typename MtdTuple::Param5 Param5; \
        mutable Tps::Private::IDisposableHolder UnpackerHolder; \
	public: \
		TPS_MTD_PROXY_CLASS_IMPL_MTD_BEGIN(mtd_) Param1 prm1, Param2 prm2, Param3 prm3, Param4 prm4, Param5 prm5 TPS_MTD_PROXY_CLASS_IMPL_MTD_END() const \
		{ \
			ThisType *This = const_cast<ThisType *>(static_cast<ThisType const *>(this)); \
			std::auto_ptr<typename ThisType::Serializer> Pack = \
				This->CreateSerializer(This->GetInstanceId(), This->GetClsId(), mtd_##ID, 5, true); \
			Pack->template PutParameter<Param1>(1, prm1); \
			Pack->template PutParameter<Param2>(2, prm2); \
			Pack->template PutParameter<Param3>(3, prm3); \
			Pack->template PutParameter<Param4>(4, prm4); \
			Pack->template PutParameter<Param5>(5, prm5); \
            UnpackerHolder.Assign(This->CallRemoteMethod(Pack).release()); \
            typename ThisType::Deserializer *Unpacker = UnpackerHolder.Get<typename ThisType::Deserializer>(); \
            Tps::Private::OutParamGetter<Param1>::Get(Unpacker, 1, prm1); \
            Tps::Private::OutParamGetter<Param2>::Get(Unpacker, 2, prm2); \
            Tps::Private::OutParamGetter<Param3>::Get(Unpacker, 3, prm3); \
            Tps::Private::OutParamGetter<Param4>::Get(Unpacker, 4, prm4); \
            Tps::Private::OutParamGetter<Param5>::Get(Unpacker, 5, prm5); \
			return Tps::Private::RetValueGetter<Ret>::Get(Unpacker); \
		} \
	};

#define TPS_MTD_STUB_CLASS_IMPL(mtd_) \
	template <typename MtdType> \
	struct mtd_##StubMtdWrap \
	{ \
		typedef MtdType MethodType; \
		enum { StubMtdId = mtd_##ID }; \
		template <typename IFaceType, typename UnpackerType> \
		static typename MethodType::Ret Call(IFaceType *iface, UnpackerType *unpacker) \
		{ \
			return Tps::Private::CallStub<MtdType>(iface, &IFaceType::mtd_, unpacker); \
		} \
	};

#endif	// !__TPS_MTD_CLASS_IMPL_H__
